home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / lang / mc302 / dosutil / tfb.c < prev    next >
C/C++ Source or Header  |  1994-03-18  |  11KB  |  496 lines

  1. /*
  2.  * A TSR file browser
  3.  *
  4.  * Copyright 1993-1994 Dave Dunfield
  5.  * All rights reserved.
  6.  *
  7.  * Permission granted for personal (non-commercial) use only.
  8.  *
  9.  * Compile command: cc tfb -fop
  10.  */
  11. #include <stdio.h>
  12. #include <window.h>
  13. #include <tsr.h>
  14.  
  15. #define SCREEN_SIZE    80        /* Width of screen */
  16. #define    LINE_SIZE    250        /* Maximum width of input line */
  17. #define    NUM_TAGS    10        /* Maximum number of tag locations */
  18. #define    NUM_FILES    10        /* Maximum number of pick files */
  19.  
  20. int tab_size = 8, line, lcount, offset, tag, file, fnext = 0,
  21.     file_info[NUM_FILES][NUM_TAGS+4], Msel, Mval[NUM_FILES];
  22.  
  23. unsigned sizeh, sizel, maxline, lines[2048][2], tags[NUM_TAGS];
  24.  
  25. char filename[NUM_FILES][51], search_string[NUM_FILES][51], *Mptr[NUM_FILES+1],
  26.     *argptr = 0;
  27.  
  28. struct WINDOW *mwin;
  29.  
  30. FILE *fp = 0;
  31.  
  32. /* Window video attributes */
  33. int attrs[] = {
  34.     WSAVE|WCOPEN|0x70,                /* 0: Message window */
  35.     WSAVE|WCOPEN|0x07,                /* 1: Main screen */
  36.     WSAVE|WBOX1|WCOPEN|0x70            /* 2: Info entry */
  37.     };
  38.  
  39. /* Form for entering filename */
  40. char *form1[] = {
  41.     64<<8|3,
  42.     "\x00\x00\x32Filename:",
  43.     0 };
  44.  
  45. /* Form for setting tab size */
  46. char *form2[] = {
  47.     30<<8|3,
  48.     "\x00\x00\x85Tab size:",
  49.     0 };
  50.  
  51. /* Form for selecting line number */
  52. char *form3[] = {
  53.     30<<8|3,
  54.     "\x00\x00\x85Line number:",
  55.     0 };
  56.  
  57. /* Form for string searches */
  58. char *form4[] = {
  59.     64<<8|3,
  60.     "\x00\x00\x32Search for:",
  61.     0 };
  62.  
  63. /* Welcome message */
  64. char hello[] =
  65.     "TFB [/ACLRS] [file] - Copyright 1993-1994 Dave Dunfield. All rights reserved.";
  66. /*
  67.  * Main file browser program
  68.  */
  69. browser()
  70. {
  71.     int i, x;
  72.     char buffer[LINE_SIZE+1];
  73.  
  74.     mwin = wopen(0, 0, 80, 1, attrs[0]);
  75.     wputs(hello);
  76.     wopen(0, 1, 80, 24, attrs[1]);
  77.     wcursor_off();
  78.  
  79.     /* If file already active... reopen */
  80.     if(fnext) {
  81.         if(!(fp = fopen(filename[file], "rb")))
  82.             fnext = 0; }
  83.  
  84.     /* If no file open... prompt for one. */
  85.     if(!fnext) {
  86.         *buffer = 0;
  87.         do {
  88.             if(argptr) {
  89.                 strcpy(buffer, argptr);
  90.                 argptr = 0; }
  91.             else if(wform(7, 10, attrs[2], form1, buffer))
  92.                 *buffer = 0;
  93.             if(!*buffer) {
  94.                 wclose();
  95.                 wclose();
  96.                 return; } }
  97.         while(!open_file(buffer));
  98.         strcpy(filename[file = fnext++], buffer); }
  99.  
  100. /* Display screen from file */
  101. display:
  102.     if(line > (lcount - 23)) line = lcount - 23;
  103.     if(line < 0) line = 0;
  104.     if(offset < 0) offset = 0;
  105.     update_status();
  106.     gotoline(line);
  107.     for(i=0; i < 24; ++i) {
  108.         wgotoxy(0, i);
  109.         if(fgets(buffer, sizeof(buffer)-1, fp))
  110.             display_line(buffer);
  111.         if((line + i) == lcount) {
  112.             *W_OPEN = 0x70;
  113.             wputs(" End of file ");
  114.             *W_OPEN = attrs[1];
  115.             wcleow();
  116.             break; } }
  117.  
  118. /* Get and process command character */
  119. command:
  120.     switch(x = wgetc()) {
  121.         case _KUA :            /* Backup one line */
  122.             --line;
  123.             goto display;
  124.         case _KDA :            /* Advance one line */
  125.             ++line;
  126.             goto display;
  127.         case _KPU :            /* Backup one page */
  128.             line -= 23;
  129.             goto display;
  130.         case _KPD :            /* Advance one page */
  131.             line += 23;
  132.             goto display;
  133.         case _CPU :            /* Go to start of file */
  134.             line = 0;
  135.             goto display;
  136.         case _CPD :            /* Go to end of file */
  137.             line = 32767;
  138.             goto display;
  139.         case _KRA :            /* Advance one column */
  140.             ++offset;
  141.             goto display;
  142.         case _KLA :            /* Backup one column */
  143.             --offset;
  144.             goto display;
  145.         case _KEN :            /* Advance 20 columns */
  146.             offset += 20;
  147.             goto display;
  148.         case _KHO :            /* Backup 20 columns */
  149.             offset -= 20;
  150.             goto display;
  151.         case _CHO :            /* Reset to 1st column */
  152.             offset = 0;
  153.             goto display;
  154.         case _K1 :            /* Display Fkey help */
  155.             w_clwin(mwin);
  156.             w_puts("1:Help 2:Goto 3:Search 4:Again 5:Gotag 6:Setag 7:Tabsize 8:Colors 9:File 10:Pick", mwin);
  157.             goto command;
  158.         case _K2 :            /* Goto line number */
  159.             x = line+1;
  160.             if(!wform(20, 10, attrs[2], form3, &x))
  161.                 line = x - 1;
  162.             goto display;
  163.         case _K3 :            /* Initial Search */
  164.             if(!wform(7, 10, attrs[2], form4, search_string[file])
  165.                 && search(search_string[file], line))
  166.                 goto display;
  167.             goto command;
  168.         case _K4 :            /* Repeat Search */
  169.             if(search(search_string[file], line+1))
  170.                 goto display;
  171.             goto command;
  172.         case _K5 :            /* Move to tag */
  173.             if((!tag_menu(15, 8)) && tags[tag])
  174.                 line = tags[tag] - 1;
  175.             goto display;
  176.         case _K6 :            /* Set tag */
  177.             if(!tag_menu(55, 8))
  178.                 tags[tag] = line + 1;
  179.             goto command;
  180.         case _K7 :            /* Set TAB size */
  181.             x = tab_size;
  182.             if(!wform(20, 10, attrs[2], form2, &x))
  183.                 tab_size = x ? x : 1;
  184.             goto display;
  185.         case _K8 :
  186.             colors();
  187.             goto display;
  188.         case _K9 :            /* Browse another file */
  189.             *buffer = 0;
  190.             if(!wform(7, 10, attrs[2], form1, buffer)) {
  191.                 save_info();
  192.                 if(open_file(buffer)) {
  193.                     strcpy(filename[file = fnext++ % NUM_FILES], buffer);
  194.                     goto display; } }
  195.             goto command;
  196.         case _K10 :            /* Pick a previously opened file */
  197.             for(i=Msel=x=0; i < NUM_FILES; ++i) {
  198.                 if(*filename[i]) {
  199.                     if(i == file)
  200.                         Msel = x;
  201.                     Mptr[x] = filename[i];
  202.                     Mval[x++] = i; } }
  203.             Mptr[x] = 0;
  204.             if(!wmenu(15, 8, attrs[2], Mptr, &Msel)) {
  205.                 save_info();
  206.                 if(open_file(filename[Msel])) {
  207.                     file = Msel;
  208.                     restore_info();
  209.                     goto display; } }
  210.             goto command;
  211.         case 0x1B :            /* exit */
  212.             save_info();
  213.             fclose(fp);
  214.             wclose();
  215.             wclose();
  216.             return; }
  217.  
  218. /* Command key not recognized... */
  219.     wputc(7);
  220.     goto command;
  221. }
  222.  
  223. /*
  224.  * Open and index a file
  225.  */
  226. open_file(name)
  227.     char *name;
  228. {
  229.     int c;
  230.  
  231.     /* Attempt to open the file - report if failure */
  232.     if(!(c = fopen(name, "rb"))) {
  233.         w_clwin(mwin);
  234.         w_printf(mwin,"Unable to access: '%s'", name);
  235.         return 0; }
  236.  
  237.     w_clwin(mwin);
  238.     w_printf(mwin,"Indexing '%s'...", name);
  239.  
  240.     /* Close previously open file (if any) */
  241.     if(fp)
  242.         fclose(fp);
  243.     fp = c;
  244.  
  245.     /* Reset viewer file control variables */
  246.     sizeh = sizel = maxline = lcount = line = offset = tag = 0;
  247.     for(c=0; c < NUM_TAGS; ++c)
  248.         tags[c] = 0;
  249.  
  250.     /* Build table of line numbers .vs. file offsets */
  251.     while((c = getc(fp)) != EOF) {
  252.         if(!++sizel)
  253.             ++sizeh;
  254.         if(c == '\n') {
  255.         /*    if(!++sizel)
  256.                 ++sizeh; */
  257.             if(!(++lcount & 0x1F)) {
  258.                 lines[maxline][0] = sizel;
  259.                 lines[maxline++][1] = sizeh; } } }
  260.  
  261.     return -1;
  262. }
  263.  
  264. /*
  265.  * Display status in the message window
  266.  */
  267. update_status()
  268. {
  269.     w_gotoxy(0, 0, mwin);
  270.     w_printf(mwin,"%-50s Line: %u of %u, Col: %u", filename[file], line+1, lcount, offset+1);
  271.     w_cleow(mwin);
  272. }
  273.  
  274. /*
  275.  * Position file to line 'n'
  276.  */
  277. gotoline(line)
  278.     unsigned line;
  279. {
  280.     int c, i;
  281.  
  282.     rewind(fp);
  283.  
  284.     /* If more than 32 lines... seek to it */
  285.     if(i = line >> 5) {
  286.         --i;
  287.         fseek(fp, lines[i][1], lines[i][0], 0); }
  288.  
  289.     /* Read till we get to exact line */
  290.     i = line & 0x1F;
  291.     while(i) {
  292.         if((c = getc(fp)) == EOF)
  293.             return -1;
  294.         if(c == '\n')
  295.             --i; }
  296.  
  297.     return 0;
  298. }
  299.  
  300. /*
  301.  * Display a line with tabs expanded
  302.  */
  303. display_line(text)
  304.     char *text;
  305. {
  306.     int p, o;
  307.     unsigned char c;
  308.  
  309.     o = offset + SCREEN_SIZE;
  310.     p = 0;
  311.     while((c = *text++) && (p < o)) {
  312.         if(c == '\t') {                /* tab */
  313.             do
  314.                 if(p >= offset)
  315.                     wputc(' ');
  316.             while(++p % tab_size); }
  317.         else if(c != '\r') {                        /* not a tab */
  318.             if(++p > offset) {
  319.                 if(c < ' ') {        /* Control character */
  320.                     *W_OPEN = 0x70;
  321.                     wputc(c + 0x40);
  322.                     *W_OPEN = attrs[1];
  323.                     continue; }
  324.                 wputc((c <= '~') ? c : 0xFE); } } }
  325.     if(p < o)
  326.         wcleol();
  327. }
  328.  
  329. /*
  330.  * Search for string in file
  331.  */
  332. search(string, l)
  333.     char *string;
  334.     int l;
  335. {
  336.     char buffer[LINE_SIZE+1];
  337.  
  338.     w_clwin(mwin);
  339.     w_printf(mwin, "Searching from line %u for '%s'... ", l+1, string);
  340.     gotoline(l);
  341.     while(fgets(buffer, sizeof(buffer)-1, fp)) {
  342.         if(inline(buffer, string)) {
  343.             line = l;
  344.             return -1; }
  345.         ++l; }
  346.     w_printf(mwin, "Not found!", string);
  347.     return 0;
  348. }
  349.  
  350. /*
  351.  * Test for string occuring within a line.
  352.  * We could easily do this in 'C', however its a good chance to show
  353.  * off inline assembly language, and get a slight speed improvement.
  354.  */
  355. inline(line, string) asm
  356. {
  357.         MOV        SI,6[BP]        ; Get line
  358. inl1:    MOV        DI,4[BP]        ; Get string
  359. inl2:    MOV        AL,[DI]            ; Get char from string
  360.         MOV        AH,[SI]            ; Get char from line
  361.         AND        AL,AL            ; End of string?
  362.         JZ        inl3            ; Yes, we have match
  363.         INC        SI                ; Advance line
  364.         INC        DI                ; Advance string
  365.         CMP        AL,AH            ; *line == *string?
  366.         JZ        inl2            ; Yes, keep looking
  367.         AND        AH,AH            ; End of string?
  368.         JNZ        inl1            ; No, keep trying
  369. ; End of line... string was not found
  370.         XOR        AX,AX            ; 0 = Not found
  371.         JMP SHORT inl4            ; And exit
  372. ; Found string
  373. inl3:    MOV        AX,-1            ; 1 = Success
  374. inl4:
  375. }
  376.  
  377. /*
  378.  * Save viewer information for current file.
  379.  */
  380. save_info()
  381. {
  382.     int i, *ptr;
  383.     ptr = file_info[file];
  384.     *ptr = line;
  385.     *++ptr = offset;
  386.     *++ptr = tab_size;
  387.     *++ptr = tag;
  388.     for(i=0; i < NUM_TAGS; ++i)
  389.         *++ptr = tags[i];
  390. }
  391.  
  392. /*
  393.  * Reload viewer information for current file.
  394.  */
  395. restore_info()
  396. {
  397.     int i, *ptr;
  398.     ptr = file_info[file];
  399.     line = *ptr;
  400.     offset = *++ptr;
  401.     tab_size = *++ptr;
  402.     tag = *++ptr;
  403.     for(i=0; i < NUM_TAGS; ++i)
  404.         tags[i] = *++ptr;
  405. }
  406.  
  407. /*
  408.  * Build and perform a menu of tag line numbers.
  409.  */
  410. tag_menu(x, y)
  411.     int x, y;
  412. {
  413.     int i;
  414.     char *tagnames[NUM_TAGS+1], text[NUM_TAGS][6];
  415.     for(i=0; i < NUM_TAGS; ++i) {
  416.         if(tags[i])
  417.             sprintf(tagnames[i] = text[i], "%u", tags[i]);
  418.         else
  419.             tagnames[i] = "-----"; }
  420.     tagnames[NUM_TAGS] = 0;
  421.     return wmenu(x, y, attrs[2], tagnames, &tag);
  422. }
  423.  
  424. /*
  425.  * Set window colors
  426.  */
  427. colors()
  428. {
  429.     int num, color, f, b;
  430.     static char *cnames[] = {
  431.         "Message line",
  432.         "Main screen",
  433.         "Pop up windows" };
  434.  
  435.     num = 0;
  436.     for(;;) {
  437.         color = attrs[num];
  438.         f = color & 0x0F;
  439.         b = color & 0xF0;
  440.         wopen(20, 9, 32, 7, (WSAVE|WCOPEN|WBOX2)|(color & 0xFF));
  441.         wcursor_off();
  442.         *W_OPEN = (f << 4) | (b >> 4);
  443.         wputs(cnames[num]);
  444.         *W_OPEN = color;
  445.         wputs("\n\nUp/Down    = Change forground\n");
  446.         wputs("Left/Right = Change background\n");
  447.         wputs("PgUp/PgDn  = Change screen");
  448.         switch(wgetc()) {
  449.             case 0x1B :
  450.                 wclose();
  451.                 *mwin = attrs[0];
  452.                 *W_OPEN = attrs[1];
  453.                 return;
  454.             case _KPU : num = (num + 1) % 3;    break;
  455.             case _KPD : num = (num + 2) % 3;    break;
  456.             case _KUA : ++f;                    goto setcolor;
  457.             case _KDA : --f;                    goto setcolor;
  458.             case _KRA : b += 16;                goto setcolor;
  459.             case _KLA : b -= 16;
  460.             setcolor:
  461.                 attrs[num] = (color & 0xFF00) | (f & 0x0f) | (b & 0xF0);
  462.             default: }
  463.         wclose(); }
  464. }
  465.  
  466. /*
  467.  * Main program - parse arguments, and start browser (if not TSR).
  468.  */
  469. main(argc, argv)
  470.     int argc;
  471.     char *argv[];
  472. {
  473.     int i;
  474.  
  475.     /* At startup, zero filenames & search strings */
  476.     for(i=0; i < NUM_FILES; ++i)
  477.         *filename[i] = *search_string[i] = 0;
  478.  
  479.     /* If not TSR, activate browser now */
  480.     if((argc < 2) || (*(argptr = argv[1]) != '/')) {
  481.         browser();
  482.         return; }
  483.  
  484.     /* TSR... parse hotkeys & set TSR vectors */
  485.     i = 0;
  486.     while(*++argptr) switch(toupper(*argptr)) {
  487.         case 'A' : i |= ALT;        break;
  488.         case 'C' : i |= CONTROL;    break;
  489.         case 'L' : i |= L_SHIFT;    break;
  490.         case 'R' : i |= R_SHIFT;    break;
  491.         case 'S' : i |= SYS_REQ;    break;
  492.         default: abort("\nInvalid HOTKEY"); }
  493.     argptr = (argc > 2) ? argv[2] : 0;
  494.     tsr(&browser, i, 10000);
  495. }
  496.